package net.entelijan.cobean.util;

import java.io.Serializable;
import java.util.Comparator;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

public class PropertyComparator<T> implements Comparator<T>, Serializable {

	private static final long serialVersionUID = 1L;

	private String propertyName;

	private boolean ascending = true;

	public PropertyComparator() {
		super();
	}

	public PropertyComparator(String propertyName, boolean ascending) {
		super();
		this.propertyName = propertyName;
		this.ascending = ascending;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public int compare(T o1, T o2) {
		int re;
		Comparable v1 = readProperty(o1);
		Comparable v2 = readProperty(o2);
		if (ascending) {
			if (v1 == null && v2 == null) {
				re = 0;
			} else if (v2 == null) {
				re = -1;
			} else if (v1 == null) {
				re = 1;
			} else {
				re = v1.compareTo(v2);
			}
		} else {
			if (v1 == null && v2 == null) {
				re = 0;
			} else if (v2 == null) {
				re = 1;
			} else if (v1 == null) {
				re = -1;
			} else {
				re = v2.compareTo(v1);
			}
		}
		return re;
	}

	@SuppressWarnings({ "rawtypes" })
	private Comparable readProperty(T obj) {
		BeanWrapper wrapper = new BeanWrapperImpl(obj);
		return (Comparable) wrapper.getPropertyValue(this.propertyName);
	}

	public void setPropertyName(String propertyName) {
		this.propertyName = propertyName;
	}

	public String getPropertyName() {
		return propertyName;
	}

	public boolean isAscending() {
		return ascending;
	}

	public void setAscending(boolean ascending) {
		this.ascending = ascending;
	}

}
